
package com.hlkj.pay.app.merchant.ext.impl.fuyou.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.constant.FuYouConstant;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.dto.FuYouAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.fuyou.dto.FuYouConfig;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessLicenseDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.util.MerchantUtils;

import cn.hutool.extra.ftp.Ftp;
import cn.hutool.extra.ftp.FtpConfig;
import cn.hutool.extra.ftp.FtpMode;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import net.dreamlu.mica.core.utils.StringPool;

/**
 * 汇付 商户进件参数处理
 * 
 * @author HlpayTeam
 * @date 2024/09/26 12:02
 */
@Slf4j
public class FuYouMerchantCommonParamsHandle {

    private static Map<String, String> setCdMap = new HashMap<>();

    public CommonResult<FuYouConfig> channelConfig(ProviderChannelConfigDO providerChannelConfigDO) {
        // 移除config 不需要的 属性
        String channelConfig = providerChannelConfigDO.getParamsConfig();
        Map<String, String> paramsConfigValue = JsonUtils.parseObject(channelConfig, Map.class);
        FuYouConfig bean = new FuYouConfig();
        Map<String, Object> objectMap = BeanUtil.toMap(bean);
        Set<String> keys = objectMap.keySet();
        // 使用 keySet() 过滤 Map
        paramsConfigValue.keySet().removeIf(key -> !keys.contains(key));
        channelConfig = JsonUtils.toJsonString(paramsConfigValue);
        providerChannelConfigDO.setParamsConfig(channelConfig);
        // 配置转换
        try {
            FuYouConfig fuYouConfig = JsonUtils.parseObject(channelConfig, FuYouConfig.class);
            if (!StringUtils.hasText(fuYouConfig.getInsCd())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,机构号 为空");
            }
            if (!StringUtils.hasText(fuYouConfig.getRsaPublicKey())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,富有公钥 为空");
            }
            if (!StringUtils.hasText(fuYouConfig.getRsaPrivateKey())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,服务商私钥 为空");
            }
            if (!StringUtils.hasText(fuYouConfig.getMd5Key())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,md5Key 为空");
            }
            if (!StringUtils.hasText(fuYouConfig.getFtpUrl())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,ftp 地址 为空");
            }
            if (fuYouConfig.getFtpPort() == null) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,ftp 端口 为空");
            }
            if (!StringUtils.hasText(fuYouConfig.getFtpUserName())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,ftp 用户名 为空");
            }
            if (!StringUtils.hasText(fuYouConfig.getFtpPassWord())) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,ftp 密码 为空");
            }
            if (fuYouConfig.getAutoRateBase() == null) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,自动结算费率 为空");
            }
            if (fuYouConfig.getManualRateBase() == null) {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误,手动结算费率 为空");
            }
            return CommonResult.success(fuYouConfig);
        }
        catch (Exception e) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友渠道参数配置格式错误请求失败,失败信息" + e.getMessage());
        }
    }

    public CommonResult<FuYouConfig> channelConfigSubmit(ProviderChannelConfigDO providerChannelConfigDO) {
        CommonResult<FuYouConfig> fuYouConfigCommonResult = channelConfig(providerChannelConfigDO);
        if (!fuYouConfigCommonResult.isSuccess()) {
            return fuYouConfigCommonResult;
        }
        FuYouConfig fuYouConfig = fuYouConfigCommonResult.getData();
        // 验证公钥私钥是否匹配
        // Map<String, String> params = new HashMap<>();
        // params.put("testSign", "1");
        // String paySign = "";
        // try {
        // paySign = SignUtils.getPaySign(params, fuYouConfig);
        // }
        // catch (Exception e) {
        // return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(),
        // "富友商户私钥格式错误,测试签名生成异常");
        // }
        // try {
        // Boolean verifySign = SignUtils.verifySign(params, paySign, fuYouConfig);
        // if (!verifySign) {
        // return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(),
        // "富友公钥设置错误,测试签名验签异常");
        // }
        // }
        // catch (Exception e) {
        // return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(),
        // "富友公钥格式错误,测试签名验签异常");
        // }

        // 验证 ftp是否可以登录
        CommonResult<Void> checkFtpResult = checkFtp(fuYouConfig);
        if (!checkFtpResult.isSuccess()) {
            return CommonResult.error(checkFtpResult.getCode(), checkFtpResult.getMsg());
        }
        // 结算费率
        String setCd = setCd(fuYouConfig.getAutoRateBase());
        if (!StringUtils.hasText(setCd)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友默认自动结算费率扣率套餐代码无效");
        }
        setCd = setCd(fuYouConfig.getManualRateBase());
        if (!StringUtils.hasText(setCd)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "富友默认手动结算费率扣率套餐代码无效");
        }
        return fuYouConfigCommonResult;
    }

    /**
     * 发送 post请求访问本地应用并根据传递参数不同返回不同结果
     */
    public CommonResult<Void> checkFtp(FuYouConfig fuYouConfig) {
        Ftp ftp = null;
        try {
            FtpConfig config = new FtpConfig(fuYouConfig.getFtpUrl(), fuYouConfig.getFtpPort(), fuYouConfig.getFtpUserName(), fuYouConfig.getFtpPassWord(),
                    Charset.defaultCharset());
            config.setSoTimeout(30000); // 设置10秒的超时时间
            ftp = new Ftp(config, FtpMode.Passive);
            if (ftp.pwd() != null) {
                return CommonResult.success();
            }
            else {
                return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "ftp参数错误");
            }
        }
        catch (Exception e) {
            log.error("Error uploading file: " + e.getMessage());
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "ftp参数错误,错误信息:" + e.getMessage());
        }
        finally {
            if (ftp != null) {
                try {
                    ftp.close();
                }
                catch (IOException e) {
                    return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getCode(), "ftp参数错误,错误信息:" + e.getMessage());
                }
            }
        }
    }

    public static String date(String date) {
        if (!StringUtils.hasText(date)) {
            return null;
        }
        return date.replace(StringPool.DASH, StringPool.EMPTY);
    }

    public static String setCd(BigDecimal rateBase) {
        if (CollectionUtils.isEmpty(setCdMap)) {
            // setCdMap.put("0.00", "M4045");
            setCdMap.put("0.01", "Z0371");
            setCdMap.put("0.02", "Z0089");
            setCdMap.put("0.03", "M0128");
            setCdMap.put("0.09", "M0194");
            setCdMap.put("0.10", "M0125");
            setCdMap.put("0.21", "M0139");
            setCdMap.put("0.22", "Z0413");
            setCdMap.put("0.23", "Z0323");
            setCdMap.put("0.24", "M0083");
            setCdMap.put("0.25", "M0196");
            setCdMap.put("0.26", "M0175");
            setCdMap.put("0.27", "M0174");
            setCdMap.put("0.28", "Z0194");
            setCdMap.put("0.29", "M2001");
            setCdMap.put("0.30", "M0215");
            setCdMap.put("0.31", "M2002");
            setCdMap.put("0.32", "M2003");
            setCdMap.put("0.33", "M0261");
            setCdMap.put("0.34", "M2004");
            setCdMap.put("0.35", "M0136");
            setCdMap.put("0.36", "M0340");
            setCdMap.put("0.37", "M2005");
            setCdMap.put("0.38", "M0325");
            setCdMap.put("0.39", "M2006");
            setCdMap.put("0.40", "M0022");
            setCdMap.put("0.41", "M2007");
            setCdMap.put("0.42", "M0493");
            setCdMap.put("0.43", "M0408");
            setCdMap.put("0.44", "Z0394");
            setCdMap.put("0.45", "M0068");
            setCdMap.put("0.46", "M0355");
            setCdMap.put("0.47", "M0074");
            setCdMap.put("0.48", "M0072");
            setCdMap.put("0.49", "M0356");
            setCdMap.put("0.50", "M0049");
            setCdMap.put("0.51", "M1084");
            setCdMap.put("0.52", "M0079");
            setCdMap.put("0.53", "M2009");
            setCdMap.put("0.54", "Z0392");
            setCdMap.put("0.55", "M0069");
            setCdMap.put("0.56", "M1082");
            setCdMap.put("0.57", "M1074");
            setCdMap.put("0.58", "Z0193");
            setCdMap.put("0.59", "Z0203");
            setCdMap.put("0.60", "M0027");
            setCdMap.put("0.61", "M2010");
            setCdMap.put("0.62", "M2011");
            setCdMap.put("0.63", "M0440");
            setCdMap.put("0.64", "M2012");
            setCdMap.put("0.65", "M0160");
            setCdMap.put("0.66", "M0321");
            setCdMap.put("0.67", "M2013");
            setCdMap.put("0.68", "M0499");
            setCdMap.put("0.69", "M0523");
            setCdMap.put("0.70", "M0063");
            setCdMap.put("0.71", "M0357");
            setCdMap.put("0.72", "M0327");
            setCdMap.put("0.73", "M0360");
            setCdMap.put("0.74", "M0358");
            setCdMap.put("0.75", "M0282");
            setCdMap.put("0.76", "M0326");
            setCdMap.put("0.77", "M0359");
            setCdMap.put("0.78", "M0300");
            setCdMap.put("0.79", "M0396");
            setCdMap.put("0.80", "M0009");
            setCdMap.put("0.81", "M2014");
            setCdMap.put("0.82", "Z0322");
            setCdMap.put("0.83", "M0373");
            setCdMap.put("0.84", "M2015");
            setCdMap.put("0.85", "M0033");
            setCdMap.put("0.86", "M0502");
            setCdMap.put("0.87", "M0201");
            setCdMap.put("0.88", "M0511");
            setCdMap.put("0.89", "M2016");
            setCdMap.put("0.90", "M0003");
            setCdMap.put("0.91", "M2017");
            setCdMap.put("0.92", "M0274");
            setCdMap.put("0.93", "M2018");
            setCdMap.put("0.94", "Z0204");
            setCdMap.put("0.95", "M0060");
            setCdMap.put("0.96", "Z0307");
            setCdMap.put("0.97", "Z0199");
            setCdMap.put("0.98", "M0508");
            setCdMap.put("0.99", "M2019");
            setCdMap.put("1.00", "M0011");
            setCdMap.put("1.10", "M0058");
            setCdMap.put("1.20", "D3017");
            setCdMap.put("1.30", "M0113");
        }
        if (rateBase.compareTo(new BigDecimal(0)) == 0) {
            return "M0000";
        }
        String rateBaseString = MerchantUtils.bigDecimalToString2(rateBase);
        log.info("rateBaseString:{}", rateBaseString);
        return setCdMap.get(rateBaseString);
    }

    public static String companyType(Integer type, MerchantAccessLicenseDO merchantAccessLicense) {
        String companyType = merchantAccessLicense.getCompanyType();
        String licenseCode = merchantAccessLicense.getLicenseCode();
        // 企业类型：
        // 1：政府机构
        // 2：国营企业
        // 3：私营企业
        // 4：外资企业
        // 5：个体工商户
        // 6：其它组织
        // 7：事业单位
        // 8：业主委员会；

        // 0 企业商户：营业执照（license_no填15位长的营业执照编号）
        // 1 企业商户：三证合一（license_no填18位长的三证合一营业执照编号）
        // A 小微商户：身份证(一证下机)
        // B 个体户工商户（个体工商户不论证件是营业执照还是三证合一都传 B）
        // 2 事业单位
        // E 民办非企业单位
        MerchantEnum.MERCHANT_TYPE merchantType = MerchantEnum.MERCHANT_TYPE.from(type);
        switch (merchantType) {
            case PERSONAL:
                return "A";
            default:
                if (!StringUtils.hasText(companyType)) {
                    return null;
                }
                switch (companyType) {
                    case "1":
                    case "2":
                    case "3":
                    case "4":
                        if (licenseCode.length() != 15) {
                            return "1";
                        }
                        else {
                            return "0";
                        }
                    case "5":
                        return "B";
                    case "6":
                        return null;
                    case "7":
                        return "2";
                    case "8":
                        return null;
                    default:
                        return null;
                }
        }
    }

    public static String licenseType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1：营业执照
        // 2：营业执照(多证合一)
        // 3：事业单位法人证书
        // 4：社会团体法人登记证书
        // 5：民办非企业单位登记证书
        // 6：基金会法人登记证书
        // 7：宗教活动场所登记证
        // 8：其他证书/批文/证明
        // 9：执业许可证/执业证
        // 10：基层群众性自治组织特别法人统一社会信用代码证
        // 11：农村集体经济组织登记证
        // 12：业主委员会备案证明

        // NATIONAL_LEGAL：营业执照
        // NATIONAL_LEGAL_MERGE：营业执照(多证合一)
        // INST_RGST_CTF：事业单位法人证书
        // CERTIFICATE_TYPE_0001：社会团体法人登记证书
        // CERTIFICATE_TYPE_0002：民办非企业单位登记证书
        // CERTIFICATE_TYPE_0003：基金会法人登记证书
        // CERTIFICATE_TYPE_0004：宗教活动场所登记证
        // CERTIFICATE_TYPE_0005：其他证书/批文/证明
        // CERTIFICATE_TYPE_0006：执业许可证/执业证
        // CERTIFICATE_TYPE_0007：基层群众性自治组织特别法人统一社会信用代码证
        // CERTIFICATE_TYPE_0008：农村集体经济组织登记证
        // OWNERS_COMMITTEE：业主委员会备案证明
        switch (code) {
            case "1":
                return "NATIONAL_LEGAL";
            case "2":
                return "NATIONAL_LEGAL_MERGE";
            case "3":
                return "INST_RGST_CTF";
            case "4":
                return "CERTIFICATE_TYPE_0001";
            case "5":
                return "CERTIFICATE_TYPE_0002";
            case "6":
                return "CERTIFICATE_TYPE_0003";
            case "7":
                return "CERTIFICATE_TYPE_0004";
            case "8":
                return "CERTIFICATE_TYPE_0005";
            case "9":
                return "CERTIFICATE_TYPE_0006";
            case "10":
                return "CERTIFICATE_TYPE_0007";
            case "11":
                return "CERTIFICATE_TYPE_0008";
            case "12":
                return "OWNERS_COMMITTEE";
            default:
                return null;
        }
    }

    public static String certType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1:身份证
        // 2:护照
        // 3:军官证
        // 4:士兵证
        // 5:回乡证
        // 6:户口本
        // 7:外国护照
        // 8:其他
        // 9:暂住证
        // 10:警官证
        // 11:文职干部证
        // 12:港澳台同胞通行证
        // 13:外国人居留证
        // 14:台胞证
        // 15:港澳台居住证
        // 16：营业执照 （只有部分场景才会用到 如 受益人和股东）

        // 00:身份证
        // 01:护照
        // 02:军官证
        // 03:士兵证
        // 04:回乡证
        // 05:户口本
        // 06:外国护照
        // 07:其他
        // 08:暂住证
        // 09:警官证
        // 10:文职干部证
        // 11:港澳台同胞通行证
        // 13:外国人居留证
        // 14:台胞证
        // 15:港澳台居住证
        switch (code) {
            case "1":
                return "0";
            default:
                return null;
        }
    }

    public FuYouAppChannelParams fuYouAppChannelParams(MerchantAppChannelDO merchantAppChannelDO) {
        return JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), FuYouAppChannelParams.class);
    }

    public String domain(boolean test) {
        return test ? FuYouConstant.MERCHANT_DOMAIN_TEST : FuYouConstant.MERCHANT_DOMAIN_PROD;
    }

    public String domainSettle(boolean test) {
        return test ? FuYouConstant.MERCHANT_SETTLE_DOMAIN_TEST : FuYouConstant.MERCHANT_SETTLE_DOMAIN_PROD;
    }
}
